Metiers and things

In my ignorance I assumed that the metiers, targets and gears in the ICES vocabulary were hierarchical. In the sense that if one has a valid metier level 6, one could derive valid metier level 5, target and gear from that. Here a little script is provided that shows that this is not quite the case.
code
rtip
Author

Einar Hjörleifsson

Published

July 17, 2025

First some convenience wrappers

Not really needed here, but I use these functions elsewhere:

library(tidyverse)
#' Derive gear from metier 5 or 6
#' 
#' Obtain gear type (sometimes wrongly called metier 4?) from metier5 or  6
#'
#' @param x A character vector
#'
#' @return A vector
#' @export
#'
rb_gear_from_metier <- function(x) {
  x |> stringr::str_split("_") |> purrr::map_chr(1)
}
#' Derive target from metier 5 or 6
#'
#' Not to be confused with metier 5
#' 
#' @param x A character vector
#'
#' @return A vector
#' @export
#'
rb_target_from_metier <- function(x) {
  x |> stringr::str_split("_") |> purrr::map_chr(2)
}
#' Derive metier 5 from metier 6
#'
#' Not to be confused with target assemblage
#' 
#' @param x A character vector
#'
#' @return A vector
#' @export
#'
rb_met5_from6 <- function(x) {
  sapply(strsplit(x, "_"), function(x) paste(x[1:2], collapse = "_"))
}

The test

Steps:

  • Get all the metier level 6 from ICES
  • Derive metier level5, target and gear from metier level 6
  • Test if derived values are available (valid) using ICES vocabulary
m6 <- 
  icesVocab::getCodeList("Metier6_FishingActivity") |> 
  as_tibble() |> 
  select(key = Key, desc = Description, dep = Deprecated) |> 
  # get rid of some mess
  mutate(desc = stringr::str_remove(desc, ", see.*device")) |> 
  mutate(gear = rb_gear_from_metier(key),
         target = rb_target_from_metier(key),
         met5 = rb_met5_from6(key)) |>  
  mutate(
    v_gear = 
      case_when(gear %in% icesVocab::getCodeList("GearType")$Key ~ TRUE,
                .default = FALSE),
    v_target = 
      case_when(target %in% icesVocab::getCodeList("TargetAssemblage")$Key ~ TRUE,
                .default = FALSE),
    v_met5 = 
      case_when(met5 %in% icesVocab::getCodeList("Metier5_FishingActivity")$Key ~ TRUE,
                .default = FALSE)
  )
m6 |> count(v_gear, v_target, v_met5)
# A tibble: 6 × 4
  v_gear v_target v_met5     n
  <lgl>  <lgl>    <lgl>  <int>
1 FALSE  FALSE    TRUE       1
2 FALSE  TRUE     FALSE      2
3 FALSE  TRUE     TRUE      11
4 TRUE   FALSE    TRUE       2
5 TRUE   TRUE     FALSE     37
6 TRUE   TRUE     TRUE    1167
m6 |> 
  filter(!v_gear | !v_target | !v_met5) |> 
  select(key, dep, ends_with("gear"), ends_with("target"), ends_with("met5")) |> 
  knitr::kable(caption = "Something wrotten in the State of Denmark")
Something wrotten in the State of Denmark
key dep gear v_gear target v_target met5 v_met5
DIV_CEP_0_0_0 FALSE DIV FALSE CEP TRUE DIV_CEP TRUE
DIV_DES_0_0_0 FALSE DIV FALSE DES TRUE DIV_DES TRUE
DIV_MOL_0_0_0 FALSE DIV FALSE MOL TRUE DIV_MOL TRUE
DRB_SWD_>0_0_0 FALSE DRB TRUE SWD FALSE DRB_SWD TRUE
DRH_MOL_>0_0_0 FALSE DRH FALSE MOL TRUE DRH_MOL TRUE
FOO_CRU_0_0_0 FALSE FOO FALSE CRU TRUE FOO_CRU TRUE
FOO_MOL_0_0_0 FALSE FOO FALSE MOL TRUE FOO_MOL TRUE
FYK_CRU_>0_0_0 FALSE FYK TRUE CRU TRUE FYK_CRU FALSE
GES_CAT_0_0_0 FALSE GES FALSE CAT TRUE GES_CAT TRUE
GNC_FIF_<16_0_0 FALSE GNC TRUE FIF TRUE GNC_FIF FALSE
GNC_FIF_>=16_0_0 FALSE GNC TRUE FIF TRUE GNC_FIF FALSE
GNC_FIF_>0_0_0 FALSE GNC TRUE FIF TRUE GNC_FIF FALSE
GNS_MPD_>=220_0_0 FALSE GNS TRUE MPD TRUE GNS_MPD FALSE
GNS_MPD_>0_0_0 FALSE GNS TRUE MPD TRUE GNS_MPD FALSE
GNS_MPD_100-119_0_0 FALSE GNS TRUE MPD TRUE GNS_MPD FALSE
GNS_MPD_120-219_0_0 FALSE GNS TRUE MPD TRUE GNS_MPD FALSE
GNS_SLP_<16_0_0 FALSE GNS TRUE SLP TRUE GNS_SLP FALSE
GNS_SLP_>=16_0_0 FALSE GNS TRUE SLP TRUE GNS_SLP FALSE
GNS_SLP_>0_0_0 FALSE GNS TRUE SLP TRUE GNS_SLP FALSE
GTN_SPF_<16_0_0 FALSE GTN TRUE SPF TRUE GTN_SPF FALSE
GTN_SPF_>=16_0_0 FALSE GTN TRUE SPF TRUE GTN_SPF FALSE
GTN_SPF_>0_0_0 FALSE GTN TRUE SPF TRUE GTN_SPF FALSE
HMP_MOL_0_0 FALSE HMP FALSE MOL TRUE HMP_MOL FALSE
HMS_SWD_0_0_0 FALSE HMS FALSE SWD FALSE HMS_SWD TRUE
LA_LPF_<14_0_0 FALSE LA TRUE LPF TRUE LA_LPF FALSE
LA_LPF_<14_0_0_0 TRUE LA TRUE LPF TRUE LA_LPF FALSE
LA_LPF_>=14_0_0 FALSE LA TRUE LPF TRUE LA_LPF FALSE
LA_LPF_>0_0_0 FALSE LA TRUE LPF TRUE LA_LPF FALSE
LA_SLP_<14_0_0 FALSE LA TRUE SLP TRUE LA_SLP FALSE
LA_SLP_<14_0_0_0 TRUE LA TRUE SLP TRUE LA_SLP FALSE
LA_SLP_>=14_0_0 FALSE LA TRUE SLP TRUE LA_SLP FALSE
LA_SLP_>0_0_0 FALSE LA TRUE SLP TRUE LA_SLP FALSE
LLS_LPF_0_0_0 FALSE LLS TRUE LPF TRUE LLS_LPF FALSE
LN_DEF_0_0_0 FALSE LN FALSE DEF TRUE LN_DEF TRUE
LN_SPF_0_0_0 FALSE LN FALSE SPF TRUE LN_SPF TRUE
LTL_FIF_0_0_0 FALSE LTL TRUE FIF TRUE LTL_FIF FALSE
MIS_SWD_0_0_0 FALSE MIS TRUE SWD FALSE MIS_SWD TRUE
OTM_CRU_>0_0_0 FALSE OTM TRUE CRU TRUE OTM_CRU FALSE
OTM_CRU_16-31_0_0 FALSE OTM TRUE CRU TRUE OTM_CRU FALSE
OTT_SPF_<16_0_0 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_>=120_3_120 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_>0_0_0 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_105-115_1_110 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_105-115_1_120 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_115-120_0_0 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_115-120_3_115 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_16-31_0_0 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_32-89_0_0 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
OTT_SPF_90-104_0_0 FALSE OTT TRUE SPF TRUE OTT_SPF FALSE
SBV_DEF_>0_0_0 FALSE SBV TRUE DEF TRUE SBV_DEF FALSE
SV_DEF_>0_0_0 FALSE SV FALSE DEF TRUE SV_DEF TRUE
SV_FIF_>0_0_0 FALSE SV FALSE FIF TRUE SV_FIF TRUE
SX_DEF_0_0_0 FALSE SX FALSE DEF TRUE SX_DEF FALSE

Check going from metier level 5

Steps:

  • Get all the metier level 5 from ICES
  • Derive target and gear from metier level 5
  • Test if derived values are available (valid) using ICES vocabulary
m5 <- 
  icesVocab::getCodeList("Metier5_FishingActivity") |> 
  as_tibble() |> 
  select(key = Key, desc = Description, dep = Deprecated) |> 
  mutate(gear = rb_gear_from_metier(key),
         target = rb_target_from_metier(key)) |>  
  mutate(v_gear = case_when(gear %in% icesVocab::getCodeList("GearType")$Key ~ TRUE,
                            .default = FALSE),
         v_target = case_when(target %in% icesVocab::getCodeList("TargetAssemblage")$Key ~ TRUE,
                              .default = FALSE))
m5 |> count(v_gear, v_target)
# A tibble: 4 × 3
  v_gear v_target     n
  <lgl>  <lgl>    <int>
1 FALSE  FALSE        1
2 FALSE  TRUE        11
3 TRUE   FALSE        2
4 TRUE   TRUE       160
m5 |> 
  filter(!v_gear | !v_target) |> 
  select(key, dep, ends_with("gear"), ends_with("target"), ends_with("met5")) |> 
  knitr::kable(caption = "Something wrotten in the State of Denmark")
Something wrotten in the State of Denmark
key dep gear v_gear target v_target
DIV_CEP FALSE DIV FALSE CEP TRUE
DIV_DES FALSE DIV FALSE DES TRUE
DIV_MOL FALSE DIV FALSE MOL TRUE
DRB_SWD FALSE DRB TRUE SWD FALSE
DRH_MOL FALSE DRH FALSE MOL TRUE
FOO_CRU FALSE FOO FALSE CRU TRUE
FOO_MOL FALSE FOO FALSE MOL TRUE
GES_CAT FALSE GES FALSE CAT TRUE
HMS_SWD FALSE HMS FALSE SWD FALSE
LN_DEF FALSE LN FALSE DEF TRUE
LN_SPF FALSE LN FALSE SPF TRUE
MIS_SWD FALSE MIS TRUE SWD FALSE
SV_DEF FALSE SV FALSE DEF TRUE
SV_FIF FALSE SV FALSE FIF TRUE

The Icelandic gear table

gear_mapping <- nanoparquet::read_parquet(here::here("data/gear/gear_mapping.parquet"))
gear_mapping |> knitr::kable(caption = "Icelandic gear mapping")
Icelandic gear mapping
agf_gid veiðarfæri gear target met5 met6 s1 s2 orri
1 Skötuselsnet GNS DEF GNS_DEF GNS_DEF_>0_0_0 0.000 2.500 91
2 Þorskfisknet GNS DEF GNS_DEF GNS_DEF_>0_0_0 0.000 1.700 2
3 Grásleppunet GNS DEF GNS_DEF GNS_DEF_>0_0_0 0.000 1.700 25
4 Rauðmaganet GNS DEF GNS_DEF GNS_DEF_>0_0_0 0.000 1.700 29
5 Reknet GND SPF GND_SPF GND_SPF_>0_0_0 0.050 1.125 11
6 Botnvarpa OTB DEF OTB_DEF OTB_DEF_>=120_0_0 2.625 4.700 6
7 Humarvarpa OTB CRU OTB_CRU OTB_CRU_90-99_1_120 2.375 3.700 9
8 Rækjuvarpa OTB CRU OTB_CRU OTB_CRU_40-54_0_0 1.750 3.000 14
9 Flotvarpa OTM SPF OTM_SPF OTM_SPF_>0_0_0 2.625 6.000 7
10 Nót PS SPF PS_SPF PS_SPF_>0_0_0 0.000 1.700 10
11 Dragnót SDN DEF SDN_DEF SDN_DEF_>=120_0_0 0.250 2.900 5
12 Lína LLS DEF LLS_DEF LLS_DEF_0_0_0 0.375 2.750 1
13 Landbeitt lína LLS DEF LLS_DEF LLS_DEF_0_0_0 0.375 2.750 72
14 Handfæri LHM DEF LHM_DEF LHM_DEF_0_0_0 0.025 1.700 3
15 Plógur DRB DES DRB_DES DRB_DES_>0_0_0 1.200 2.900 15
16 Gildra FPO DEF FPO_DEF FPO_DEF_>0_0_0 0.100 2.000 16
17 Annað - Hvað MIS DWF MIS_DWF MIS_DWF_0_0_0 NA NA 99
18 Eldiskví NA NA NA NA NA NA NA
19 Sjóstöng LHP FIF LHP_FIF LHP_FIF_0_0_0 0.125 1.250 43
20 Kræklingalína NA NA NA NA NA NA 42
21 Línutrekt LLS DEF LLS_DEF LLS_DEF_0_0_0 0.100 2.200 1
22 Grálúðunet GNS DEF GNS_DEF GNS_DEF_>0_0_0 0.050 1.400 92
23 Kafari DIV DES DIV_DES DIV_DES_0_0_0 NA NA 41
24 Sláttuprammi HMS SWD HMS_SWD HMS_SWD_0_0_0 0.000 1.400 NA
25 Þaraplógur HMS SWD HMS_SWD HMS_SWD_0_0_0 2.300 4.000 NA

So which gears do not pass the test:

gear_mapping |> 
  filter(!is.na(gear)) |> 
  mutate(
    v_gear = 
      case_when(gear %in% icesVocab::getCodeList("GearType")$Key ~ TRUE,
                .default = FALSE),
    v_target = 
      case_when(target %in% icesVocab::getCodeList("TargetAssemblage")$Key ~ TRUE,
                .default = FALSE),
    v_met5 = 
      case_when(met5 %in% icesVocab::getCodeList("Metier5_FishingActivity")$Key ~ TRUE,
                .default = FALSE),
    v_met6 = 
      case_when(met6 %in% icesVocab::getCodeList("Metier6_FishingActivity")$Key ~ TRUE,
                .default = FALSE)
  ) |> 
  filter(!v_gear | !v_target | !v_met5 | !v_met6) |> 
  knitr::kable(caption = "Icelandic gears that pass metier level 5 and 6, but not gear and target")
Icelandic gears that pass metier level 5 and 6, but not gear and target
agf_gid veiðarfæri gear target met5 met6 s1 s2 orri v_gear v_target v_met5 v_met6
23 Kafari DIV DES DIV_DES DIV_DES_0_0_0 NA NA 41 FALSE TRUE TRUE TRUE
24 Sláttuprammi HMS SWD HMS_SWD HMS_SWD_0_0_0 0.0 1.4 NA FALSE FALSE TRUE TRUE
25 Þaraplógur HMS SWD HMS_SWD HMS_SWD_0_0_0 2.3 4.0 NA FALSE FALSE TRUE TRUE

So here we have a bit of a catch22, metier 5 and 6 valid but not gear (except DRB) and target.